#if defined(ESP32)
#include <WiFi.h>
#include <HTTPClient.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#endif
#include <EEPROM.h>
#include <Ticker.h>
#include <ArduinoJson.h>
WiFiClient client_bemfa_WiFiClient;
HTTPClient http_bemfa_HTTPClient;
#define AP_CONFIG "ok"
String UID = "";
String wxTopic="";
int httpCode = 0;
#define HOST_NAME  "bemfa"
char config_flag = 0;
#define MAGIC_NUMBER 0xAA
struct config_type {
  char stassid[32];
  char stapsw[64];
  char cuid[40];
  char ctopic[32];
  uint8_t reboot;
  uint8_t magic;
};
config_type config;
void doSmartconfig();
void saveConfig();
void initWiFi();
void loadConfig();
void restoreFactory();
void waitKey();

void doSmartconfig() {
  Serial.print(" Airkiss begin,Waiting for WeChat Config.....");
  #ifdef ESP32
  WiFi.mode(WIFI_AP_STA);
  WiFi.disconnect(true, true);
  #else
  WiFi.mode(WIFI_STA);
  WiFi.disconnect(true);
  #endif
  WiFi.beginSmartConfig();
  int cnt = 0;
  while (!WiFi.smartConfigDone()) {
    delay(500);
    cnt++;
    if (cnt >= 600) {
      delayRestart(0);
    }
  }
  if (WiFi.smartConfigDone()) {
    strcpy(config.stassid, WiFi.SSID().c_str());
    strcpy(config.stapsw, WiFi.psk().c_str());
    config.magic = 0xAA;
    saveConfig();
  }
}

void saveConfig(){
  int rand_key;
  uint8_t mac[6];
  WiFi.macAddress(mac);
  config.reboot = 0;
  #ifdef ESP32
  EEPROM.begin(512);
  #else
  EEPROM.begin(256);
  #endif
  uint8_t *p = (uint8_t*)(&config);
  for (int i = 0; i < sizeof(config); i++) {
    EEPROM.write(i, *(p + i));
  }
  EEPROM.commit();
}

Ticker delayTimer;

void delayRestart(float t) {
  delayTimer.attach(t, []() {
    ESP.restart();
  });
}

void initWiFi() {
  char temp[32];
  uint8_t mac[6];
  WiFi.macAddress(mac);
  sprintf(temp, "%s_%02X%02X%02X", HOST_NAME, mac[3], mac[4], mac[5]);
  WiFi.hostname(temp);
  if (WiFi.status() != WL_CONNECTED) {
    #ifdef ESP32
    WiFi.disconnect(true, true);//断开连接
    #else
    WiFi.disconnect(true);//断开连接
    #endif
    WiFi.mode(WIFI_STA);  // STA模式
    WiFi.begin(config.stassid, config.stapsw);  // 连接路由器
  }
  int connAttempts = 0;
  while (WiFi.status() != WL_CONNECTED) {  // 检查是否连接成功
    delay(500);
    Serial.print(".");
    connAttempts++;if (connAttempts > 20)break;
  }
  if (connAttempts >= 20) {
    Serial.println("wifi connect error");
  } else {
    Serial.println("wifi connect ok");
  }
  WiFi.softAP(temp);
}

uint8_t *p = (uint8_t*)(&config);

void loadConfig() {
  uint8_t mac[6];
  WiFi.macAddress(mac);
  #ifdef ESP32
  EEPROM.begin(512);
  #else
  EEPROM.begin(256);
  #endif
  for (int i = 0; i < sizeof(config); i++) {
    *(p + i) = EEPROM.read(i);
  }
  config.reboot = config.reboot + 1;
  if(config.reboot>=4){
    restoreFactory();
  }
  if(config.magic != 0xAA){
    config_flag = 1;
  }
  #ifdef ESP32
  EEPROM.begin(512);
  #else
  EEPROM.begin(256);
  #endif
  for (int i = 0; i < sizeof(config); i++){
    EEPROM.write(i, *(p + i));
  }
  EEPROM.commit();
  delay(2000);
  #ifdef ESP32
  EEPROM.begin(512);
  #else
  EEPROM.begin(256);
  #endif
  config.reboot = 0;
  for (int i = 0; i < sizeof(config); i++) {
    EEPROM.write(i, *(p + i));
  }
  EEPROM.commit();
  delay(2000);
}

void restoreFactory() {
  Serial.println("Restore Factory....... ");
  config.magic = 0x00;
  strcpy(config.stassid, "");
  strcpy(config.stapsw, "");
  strcpy(config.cuid, "");
  strcpy(config.ctopic, "");
  config.magic = 0x00;
  saveConfig();
  delayRestart(1);
  while (1) {
    delay(100);
  }
}

void waitKey() {
  if(config_flag == 1){
    doSmartconfig();
  }
}

void getUid(String mac) {
  String topic = mac + "{{&deviceType}}";
  if (strcmp(config.cuid, "") == 0){
    http_bemfa_HTTPClient.begin(client_bemfa_WiFiClient, "http://api.bemfa.com/api/device/v1/airkiss/?topic=" + topic + "&version={{&version}}");
    httpCode = http_bemfa_HTTPClient.GET();
    if (httpCode > 0) {
      String payload = http_bemfa_HTTPClient.getString();
      StaticJsonDocument<200> doc;  // json数据解析
      DeserializationError error = deserializeJson(doc, payload);
      if (error) {
        Serial.print(F("deserializeJson() failed: "));
        Serial.println(error.c_str());
      }
      String code = doc["code"];
      if(code == "5723200") {
        String docUID = doc["uid"];
        strcpy(config.cuid, docUID.c_str());
        strcpy(config.ctopic, topic.c_str());
        saveConfig();
      } else {
        Serial.println(" config ERROR.........");
      }
      http_bemfa_HTTPClient.end();
    }
  }
  if (strcmp(config.ctopic, "") == 0) {
    wxTopic = topic;
  } else {
    wxTopic = config.ctopic;
  }
  UID = config.cuid;
}